import './index.less';
interface IOption {
    format?: string
}
function getDateMaxDaysAndStartWeek(date: Date) {
    let currentMonthDays = new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();
    let currentMonthStartWeek = new Date(date.getFullYear(), date.getMonth()).getDay();
    return {
        startWeeK: currentMonthStartWeek,
        days: currentMonthDays
    }
}
export class ZDate {
    protected dateContent: HTMLElement;
    protected listenners: Set<(date: Date) => void> = new Set();
    protected closeLiseners: Set<() => void> = new Set();
    protected date: Date = null
    constructor(protected container: HTMLElement, protected selectDate: Date|null = null, opt:IOption = {format: 'YYYY-MM-DD'}) {
        if(!this.date) {
            this.date = new Date();
        }
    }
    public init() {
        this.dateContent = document.createElement('div') as HTMLDivElement;
        this.dateContent.setAttribute('class', 'z-date-picker');
        this.createDateModalHeader();
        this.createDateModalBody();
        let days = this.getDayList(this.date);
        this.updateDays(days, this.date?this.date: new Date());
        this.container.appendChild(this.dateContent);
        return this;
    }
    public addListener(callback: (date: Date) => void) {
        this.listenners.add(callback);
    }
    public removeListener(callback: (date: Date) => void) {
        this.listenners.delete(callback);
    }
    public addCloseListener(listener: () => void) {
        this.closeLiseners.add(listener);
    }
    public removeCloseListener(listener: () => void) {
        this.closeLiseners.delete(listener);
    }
    protected createDateModalHeader() {
        let headerEle = document.createElement('div') as HTMLDivElement;
        headerEle.setAttribute('class', 'z-date-picker-header')
        headerEle.innerHTML = `
            <div class="z-date-picker-year-change-btn z-date-picker-year-change-btn-pre"></div>
            <div class="z-date-picker-month-change-btn z-date-picker-month-change-btn-pre"></div>
            <span class="z-date-picker-year">2022年12月</span>
            <div class="z-date-picker-year-change-btn z-date-picker-month-change-btn-next"></div>
            <div class="z-date-picker-month-change-btn z-date-picker-year-change-btn-next"></div>
        `;
        headerEle.querySelector('.z-date-picker-year-change-btn-pre').addEventListener('click', this.preYear.bind(this));
        headerEle.querySelector('.z-date-picker-month-change-btn-pre').addEventListener('click', this.preMonth.bind(this));
        headerEle.querySelector('.z-date-picker-year-change-btn-next').addEventListener('click', this.nextYear.bind(this));
        headerEle.querySelector('.z-date-picker-month-change-btn-next').addEventListener('click', this.nextMonth.bind(this));
        this.dateContent.append(headerEle);
    }
    protected createDateModalBody() {
        let bodyEle = document.createElement('div') as HTMLDivElement;
        bodyEle.innerHTML = `
            <div class="z-datepicker-body">
                <div class="z-datepicker-body-head">
                    <span>日</span><span>一</span><span>二</span><span>三</span><span>四</span><span>五</span><span>六</span>
                </div>
                <div class="z-datepicker-body-content">

                </div>
            </div>
        `;
        this.dateContent.append(bodyEle);
        bodyEle.querySelector('.z-datepicker-body-content').addEventListener('click', (evt: Event) => {

        });
    }
    protected updateDays(days: number[][], date: Date) {
        if(this.dateContent.querySelector('.z-datepicker-body-days')) {
            this.dateContent.querySelector('.z-datepicker-body-days').remove();
        }
        let content = document.createElement('div') as HTMLElement;
        content.setAttribute('class', 'z-datepicker-body-days');
        let isCurrentMonthYear = (() => {
            let today = new Date();
            let todayNum = today.getDate();
            let _isCurrentTime = (today.getFullYear() === date.getFullYear() && today.getMonth() === date.getMonth());
            return (day: number) => {
                if(_isCurrentTime && day === todayNum) {
                    return true;
                }
                return false;
            }
        })();
        let isSelectedDate: (day: number) => boolean = (() => {
            if(!this.selectDate) {
                return () => {
                    return false;
                }
            }
            let _isCurrentTime = (this.selectDate.getFullYear() === date.getFullYear() && this.selectDate.getMonth() === date.getMonth());
            return (day: number) => {
                return _isCurrentTime && day === this.selectDate.getDate();
            }
        })();
        for(let i = 0; i < days.length; i++) {
            let dayRow = document.createElement('div') as HTMLDivElement;
            dayRow.setAttribute('class', 'z-datepicker-day-row')
            for(let j = 0; j < days[i].length; j++) {
                let dayCol = document.createElement('div') as HTMLElement;
                dayCol.setAttribute('class', 'z-datepicker-day-col');
                if((i < 2 && days[i][j] > 15) || (i > 2 && days[i][j] < 15)) {
                    dayCol.classList.add('z-datepicker-day-col-not-active');
                }
                if(isCurrentMonthYear(days[i][j])) {
                    dayCol.classList.add('z-datepicker-day-col-today');
                }
                if(isSelectedDate(days[i][j])) {
                    dayCol.classList.add('z-datepicker-day-col-active');
                }
                dayCol.innerText = days[i][j].toString();
                dayRow.append(dayCol);
            }
            content.append(dayRow);
        }
        this.dateContent.querySelector('.z-datepicker-body-content').append(content);
        this.dateContent.querySelector('.z-date-picker-year').innerHTML = `${date.getFullYear()}年${date.getMonth() + 1}`;
    }
    protected getDayList(_date: Date | null) {
        let date = _date || new Date();
        let currentInfo = getDateMaxDaysAndStartWeek(date);
        let preInfo = (() => {
            if(date.getMonth() === 0) {
                return getDateMaxDaysAndStartWeek(new Date(date.getFullYear() - 1, 11));
            } else {
                return getDateMaxDaysAndStartWeek(new Date(date.getFullYear(), date.getMonth() - 1));
            }
        })();
        let arr: number[] = [];
        for(let i = 1; i <= currentInfo.days; i++) {
            arr.push(i);
        }
        for(let i = 0; i < currentInfo.startWeeK; i++) {
            arr.unshift(preInfo.days - i);
        }
        let len = 7 - arr.length % 7
        for(let i = 0; i < len; i++) {
            arr.push(i + 1);
        }
        if(arr.length / 7 < 6) {
            if(arr[arr.length - 1] > 20) {
                arr.push(1);
            }
            while(arr.length / 7 < 6) {
                arr.push(arr[arr.length - 1] + 1);
            }
        }
        let result: number[][] = [];
        for(let i = 0; i < arr.length / 7; i++) {
            result.push(arr.slice(i * 7, (i + 1) * 7))
        }
        return result;
    }
    protected nextMonth() {
        if(this.date.getMonth() === 11) {
            this.date.setFullYear(this.date.getFullYear() + 1);
            this.date.setMonth(0);
        } else {
            this.date.setMonth(this.date.getMonth() + 1);
        }
        let days = this.getDayList(this.date);
        this.updateDays(days, this.date);
    }
    protected preMonth() {
        if(this.date.getMonth() === 0) {
            this.date.setFullYear(this.date.getFullYear() - 1);
            this.date.setMonth(11);
        } else {
            this.date.setMonth(this.date.getMonth() - 1);
        }
        let days = this.getDayList(this.date);
        this.updateDays(days, this.date);
    }
    protected nextYear() {
        this.date.setFullYear(this.date.getFullYear() + 1);
        let days = this.getDayList(this.date);
        this.updateDays(days, this.date);
    }
    protected preYear() {
        this.date.setFullYear(this.date.getFullYear() - 1);
        let days = this.getDayList(this.date);
        this.updateDays(days, this.date);
    }
}